/**
 * @file random_test.h
 *
 * Auxiliary tools for testing random number generation
 * 
 * @author Dahua Lin
 */

#ifndef SLIPP_RANDOM_TEST_H_
#define SLIPP_RANDOM_TEST_H_

#include <slipp/base/math_base.h>
#include <slipp/base/arrays.h>

namespace sli { namespace test {

	template<typename T>
	uarow_t get_histogram(const EIGEN_AROW(T)& x, const T& m)
	{
		index_t im = (index_t)m;
		uarow_t h = uarow_t::Constant(im, 0);

		index_t n = x.size();
		for (index_t i = 0; i < n; ++i)
		{
			index_t cx = (index_t)x(i);
			if (cx >= 0 && cx < im)
			{
				++ h(cx);
			}
		}

		return h;
	}

	template<typename T>
	bool histogram_check(const EIGEN_AROW(T)& x, const darow_t& p, double pout, double tol)
	{
		index_t m = p.size();
		index_t n = x.size();

		uarow_t h = get_histogram(x, (T)m);

		uint32_t count_out = (uint32_t)n - h.sum();

		double q = 0;

		if (pout == 0)
		{
			if (count_out > 0) return false;
		}
		else
		{
			q = double(count_out) / double(n);
			if (math::abs(q - pout) > tol) return false;
		}

		for (index_t k = 0; k < m; ++k)
		{
			q = double(h(k)) / double(n);
			if (math::abs(q - p(k)) > tol) return false;
		}

		return true;
	}


	template<typename T>
	double average_neighbor_diff(const EIGEN_AROW(T)& x)
	{
		index_t n = x.size();
		index_t m = n >> 1;

		double s = 0;
		for (index_t i = 0; i < m; ++i)
		{
			s += math::abs(x(2 * i + 1) - x(2 * i));
		}

		return s / double(m);
	}


} }

#endif 
